package com.cndym.utils;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 作者: cndym
 * 日期: 2010-5-7
 * 时间: 11:22:50
 */
public class DefaultLoaderClass {
    private static Map<String, String> map = new HashMap<String, String>();
    private static URLClassLoader urlClassLoader;
    private static List<URL> list = new ArrayList<URL>();

    static {
        URL url = DefaultLoaderClass.class.getResource("/");
        list.add(url);
        loader();
    }

    public static void add(String paths) {
        add(new String[]{paths});
    }

    public static void add(String[] paths) {
        for (String s : paths) {
            File file = new File(s);
            try {
                URL url = file.toURI().toURL();
                list.add(url);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
        loader();
    }

    private static void loader() {
        for (URL url : list) {
            try {
                String path = url.toURI().getPath();
                File file = new File(path);
                if (file.isFile()) {
                    findClassFromJar(path, map);
                } else if (file.isDirectory()) {
                    findClassFromDirectory(path, map);
                }
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        }
        URL[] arr = new URL[list.size()];
        list.toArray(arr);
        urlClassLoader = new URLClassLoader(arr, Thread.currentThread().getContextClassLoader());
    }


    public static String findByName(String name) {
        String temp = null;
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println(entry.getValue());
            if (entry.getValue().equals(name)) {
                temp = entry.getKey();
                break;
            }
        }
        return temp;
    }

    public static Class instanceClass(String name) {
        Class aClass = null;
        String className = null;
        if (name.indexOf(".") > -1) {
            className = map.get(name);
        } else {
            className = findByName(name);
        }
        if (null == className) {
            return null;
        }
        try {
            aClass = urlClassLoader.loadClass(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return aClass;
    }

    public static Object instanceObject(String name) {
        Class aClass = instanceClass(name);
        if (null != aClass) {
            try {
                return aClass.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static List<String> classList() {
        List<String> list = new ArrayList<String>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            list.add(entry.getKey());
        }
        return list;
    }


    public static void findClassFromJar(String path, Map<String, String> map) {
        if (null == map) {
            return;
        }
        File file = new File(path);
        JarFile jarFile = null;
        try {
            jarFile = new JarFile(file);
            Enumeration<JarEntry> enumeration = jarFile.entries();
            while (enumeration.hasMoreElements()) {
                JarEntry jarEntry = enumeration.nextElement();
                String name = jarEntry.getName();
                if (isClass(name)) {
                    name = name.replaceAll("/", ".");
                    name = name.replaceAll(".class", "");
                    map.put(name, className(name));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void findClassFromDirectory(String path, Map<String, String> map) {
        if (null == map) {
            return;
        }
        List<String> list = new ArrayList<String>();
        String tempPath = path.replaceAll("/", "#").substring(1);
        exeFindFiles(list, path);
        for (String s : list) {
            String temp = s.replaceAll("\\\\", "#");
            String classPath = temp.replaceAll(tempPath, "");
            classPath = classPath.replaceAll("#", ".");
            classPath = classPath.replaceAll(".class", "");
            map.put(classPath, className(classPath));
        }
    }

    public static void exeFindFiles(List<String> list, String path) {
        if (list == null) {
            return;
        }
        File file = new File(path);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                String filePath = f.getAbsolutePath();
                if (f.isFile()) {
                    if (isClass(filePath)) {
                        list.add(filePath);
                    }
                } else if (f.isDirectory()) {
                    exeFindFiles(list, filePath);
                }
            }
        }
    }


    public static String className(String name) {
        String[] arr = name.split("\\.");
        int length = arr.length;
        if (length > 0) {
            return arr[arr.length - 1];
        }
        return null;
    }

    public static boolean isClass(String value) {
        if (null == value || value.length() < 6) {
            return false;
        }
        String ext = value.substring(value.length() - 6);
        if (".class".equals(ext)) {
            return true;
        }
        return false;
    }

    public static String formatClassName(String name) {
        if (null != name && name.length() > 0) {
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        return null;
    }

}

